// Created by Windward Studios - no copyright is claimed. This code can be used in
// any manner by anyone for any reason. There is no copyright of any kind on it. You may
// use it in commercial products. You may change it without sharing those changes.
// We ask that you keep the "created by Windward Studios" in a comment at the top.

using System;
using System.Data;
using Kailua.net.windward.utils;

namespace net.windward.utils.ado
{
	/// <summary>
	/// Wraps an IDataReader. This allows us to override the various Get* methods that some databases don't handle.
	/// </summary>
	public abstract class WrDataReader : IDataReader
	{
		
		/// <summary>
		/// The IDataReader object that actually does the reads.
		/// </summary>
		protected readonly IDataReader reader;
		
		/// <summary>
		/// Create a WrDataReader object wrapping an IDataReader.
		/// </summary>
		/// <param name="reader">The IDataReader we are wrapping.</param>
		public WrDataReader(IDataReader reader)
		{
			this.reader = reader;
		}

		/// <summary>
		/// Read a timestamp field and return it as an Int64.
		/// </summary>
		/// <param name="ordinal">The ordinal of the timestamp column.</param>
		/// <returns>The timestamp with [0] as msw and [1] as lsw.</returns>
		public abstract long GetTimestamp(int ordinal);


		#region IDataReader Members

		///<summary>
		///Closes the <see cref="T:System.Data.IDataReader"></see> 0bject.
		///</summary>
		///<filterpriority>2</filterpriority>
		public virtual void Close()
		{
			reader.Close();
		}

		///<summary>
		///Returns a <see cref="T:System.Data.DataTable"></see> that describes the column metadata of the 
		/// <see cref="T:System.Data.IDataReader"></see>.
		///</summary>
		///
		///<returns>
		///A <see cref="T:System.Data.DataTable"></see> that describes the column metadata.
		///</returns>
		///
		///<exception cref="T:System.InvalidOperationException">The <see cref="T:System.Data.IDataReader"></see> is closed. </exception>
		/// <filterpriority>2</filterpriority>
		public virtual DataTable GetSchemaTable()
		{
			return reader.GetSchemaTable();
		}

		///<summary>
		///Advances the data reader to the next result, when reading the results of batch SQL statements.
		///</summary>
		///
		///<returns>
		///true if there are more rows; otherwise, false.
		///</returns>
		///<filterpriority>2</filterpriority>
		public virtual bool NextResult()
		{
			return reader.NextResult();
		}

		///<summary>
		///Advances the <see cref="T:System.Data.IDataReader"></see> to the next record.
		///</summary>
		///
		///<returns>
		///true if there are more rows; otherwise, false.
		///</returns>
		///<filterpriority>2</filterpriority>
		public virtual bool Read()
		{
			return reader.Read();
		}

		///<summary>
		///Gets a value indicating the depth of nesting for the current row.
		///</summary>
		///
		///<returns>
		///The level of nesting.
		///</returns>
		///<filterpriority>2</filterpriority>
		public virtual int Depth
		{
			get { return reader.Depth; }
		}

		///<summary>
		///Gets a value indicating whether the data reader is closed.
		///</summary>
		///
		///<returns>
		///true if the data reader is closed; otherwise, false.
		///</returns>
		///<filterpriority>2</filterpriority>
		public virtual bool IsClosed
		{
			get { return reader.IsClosed; }
		}

		///<summary>
		///Gets the number of rows changed, inserted, or deleted by execution of the SQL statement.
		///</summary>
		///
		///<returns>
		///The number of rows changed, inserted, or deleted; 0 if no rows were affected or the statement failed; and -1 for SELECT statements.
		///</returns>
		///<filterpriority>2</filterpriority>
		public virtual int RecordsAffected
		{
			get { return reader.RecordsAffected; }
		}

		#endregion

		#region IDisposable Members

		///<summary>
		///Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
		///</summary>
		///<filterpriority>2</filterpriority>
		public virtual void Dispose()
		{
			reader.Dispose();
		}

		#endregion

		#region IDataRecord Members

		///<summary>
		///Gets the name for the field to find.
		///</summary>
		///
		///<returns>
		///The name of the field or the empty string (""), if there is no value to return.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual string GetName(int ind)
		{
			return reader.GetName(ind);
		}

		///<summary>
		///Gets the data type information for the specified field.
		///</summary>
		///
		///<returns>
		///The data type information for the specified field.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual string GetDataTypeName(int ind)
		{
			return reader.GetDataTypeName(ind);
		}

		///<summary>
		///Gets the <see cref="T:System.Type"></see> information corresponding to the type of <see cref="T:System.Object"></see> that would be returned from <see cref="M:System.Data.IDataRecord.GetValue(System.Int32)"></see>.
		///</summary>
		///
		///<returns>
		///The <see cref="T:System.Type"></see> information corresponding to the type of <see cref="T:System.Object"></see> that would be returned from <see cref="M:System.Data.IDataRecord.GetValue(System.Int32)"></see>.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual Type GetFieldType(int ind)
		{
			return reader.GetFieldType(ind);
		}

		///<summary>
		///Return the value of the specified field.
		///</summary>
		///
		///<returns>
		///The <see cref="T:System.Object"></see> which will contain the field value upon return.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual object GetValue(int ind)
		{
			return reader.GetValue(ind);
		}

		///<summary>
		///Gets all the attribute fields in the collection for the current record.
		///</summary>
		///
		///<returns>
		///The number of instances of <see cref="T:System.Object"></see> in the array.
		///</returns>
		///
		///<param name="values">An array of <see cref="T:System.Object"></see> to copy the attribute fields into. </param><filterpriority>2</filterpriority>
		public virtual int GetValues(object[] values)
		{
			return reader.GetValues(values);
		}

		///<summary>
		///Return the index of the named field.
		///</summary>
		///
		///<returns>
		///The index of the named field.
		///</returns>
		///
		///<param name="name">The name of the field to find. </param><filterpriority>2</filterpriority>
		public virtual int GetOrdinal(string name)
		{
			return reader.GetOrdinal(name);
		}

		///<summary>
		///Gets the value of the specified column as a Boolean.
		///</summary>
		///
		///<returns>
		///The value of the column.
		///</returns>
		///
		///<param name="ind">The zero-based column ordinal. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual bool GetBoolean(int ind)
		{
			return reader.GetBoolean(ind);
		}

		///<summary>
		///Gets the 8-bit unsigned integer value of the specified column.
		///</summary>
		///
		///<returns>
		///The 8-bit unsigned integer value of the specified column.
		///</returns>
		///
		///<param name="ind">The zero-based column ordinal. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual byte GetByte(int ind)
		{
			return reader.GetByte(ind);
		}

		///<summary>
		///Reads a stream of bytes from the specified column offset into the buffer as an array, starting at the given buffer offset.
		///</summary>
		///
		///<returns>
		///The actual number of bytes read.
		///</returns>
		///
		///<param name="buffer">The buffer into which to read the stream of bytes. </param>
		///<param name="bufferoffset">The index for buffer to start the read operation. </param>
		///<param name="fieldOffset">The index within the field from which to start the read operation. </param>
		///<param name="ind">The zero-based column ordinal. </param>
		///<param name="length">The number of bytes to read. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual long GetBytes(int ind, long fieldOffset, byte[] buffer, int bufferoffset, int length)
		{
			return reader.GetBytes(ind, fieldOffset, buffer, bufferoffset, length);
		}

		///<summary>
		///Gets the character value of the specified column.
		///</summary>
		///
		///<returns>
		///The character value of the specified column.
		///</returns>
		///
		///<param name="ind">The zero-based column ordinal. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual char GetChar(int ind)
		{
			Trap.trap();
			return reader.GetChar(ind);
		}

		///<summary>
		///Reads a stream of characters from the specified column offset into the buffer as an array, starting at the given buffer offset.
		///</summary>
		///
		///<returns>
		///The actual number of characters read.
		///</returns>
		///
		///<param name="fieldoffset">The index within the row from which to start the read operation. </param>
		///<param name="buffer">The buffer into which to read the stream of bytes. </param>
		///<param name="bufferoffset">The index for buffer to start the read operation. </param>
		///<param name="ind">The zero-based column ordinal. </param>
		///<param name="length">The number of bytes to read. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual long GetChars(int ind, long fieldoffset, char[] buffer, int bufferoffset, int length)
		{
			return reader.GetChars(ind, fieldoffset, buffer, bufferoffset, length);
		}

		///<summary>
		///Returns the GUID value of the specified field.
		///</summary>
		///
		///<returns>
		///The GUID value of the specified field.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual Guid GetGuid(int ind)
		{
			return reader.GetGuid(ind);
		}

		///<summary>
		///Gets the 16-bit signed integer value of the specified field.
		///</summary>
		///
		///<returns>
		///The 16-bit signed integer value of the specified field.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual short GetInt16(int ind)
		{
			return reader.GetInt16(ind);
		}

		///<summary>
		///Gets the 32-bit signed integer value of the specified field.
		///</summary>
		///
		///<returns>
		///The 32-bit signed integer value of the specified field.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual int GetInt32(int ind)
		{
			return reader.GetInt32(ind);
		}

		///<summary>
		///Gets the 64-bit signed integer value of the specified field.
		///</summary>
		///
		///<returns>
		///The 64-bit signed integer value of the specified field.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual long GetInt64(int ind)
		{
			return reader.GetInt64(ind);
		}

		///<summary>
		///Gets the single-precision floating point number of the specified field.
		///</summary>
		///
		///<returns>
		///The single-precision floating point number of the specified field.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual float GetFloat(int ind)
		{
			return reader.GetFloat(ind);
		}

		///<summary>
		///Gets the double-precision floating point number of the specified field.
		///</summary>
		///
		///<returns>
		///The double-precision floating point number of the specified field.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual double GetDouble(int ind)
		{
			return reader.GetDouble(ind);
		}

		///<summary>
		///Gets the string value of the specified field.
		///</summary>
		///
		///<returns>
		///The string value of the specified field.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual string GetString(int ind)
		{
			return reader.GetString(ind);
		}

		///<summary>
		///Gets the fixed-position numeric value of the specified field.
		///</summary>
		///
		///<returns>
		///The fixed-position numeric value of the specified field.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual decimal GetDecimal(int ind)
		{
			return reader.GetDecimal(ind);
		}

		///<summary>
		///Gets the date and time data value of the specified field.
		///</summary>
		///
		///<returns>
		///The date and time data value of the spcified field.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual DateTime GetDateTime(int ind)
		{
			return reader.GetDateTime(ind);
		}

		///<summary>
		///Gets an <see cref="T:System.Data.IDataReader"></see> to be used when the field points to more remote structured data.
		///</summary>
		///
		///<returns>
		///An <see cref="T:System.Data.IDataReader"></see> to be used when the field points to more remote structured data.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual IDataReader GetData(int ind)
		{
			Trap.trap();
			return reader.GetData(ind);
		}

		///<summary>
		///Return whether the specified field is set to null.
		///</summary>
		///
		///<returns>
		///true if the specified field is set to null. Otherwise, false.
		///</returns>
		///
		///<param name="ind">The index of the field to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual bool IsDBNull(int ind)
		{
			return reader.IsDBNull(ind);
		}

		///<summary>
		///Gets the number of columns in the current row.
		///</summary>
		///
		///<returns>
		///When not positioned in a valid recordset, 0; otherwise the number of columns in the current record. The default is -1.
		///</returns>
		///<filterpriority>2</filterpriority>
		public virtual int FieldCount
		{
			get
			{
				return reader.FieldCount;
			}
		}

		///<summary>
		///Gets the column located at the specified index.
		///</summary>
		///
		///<returns>
		///The column located at the specified index as an <see cref="T:System.Object"></see>.
		///</returns>
		///
		///<param name="ind">The index of the column to get. </param>
		///<exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"></see>. </exception><filterpriority>2</filterpriority>
		public virtual object this[int ind]
		{
			get
			{
				return reader[ind];
			}
		}

		///<summary>
		///Gets the column with the specified name.
		///</summary>
		///
		///<returns>
		///The column with the specified name as an <see cref="T:System.Object"></see>.
		///</returns>
		///
		///<param name="name">The name of the column to find. </param>
		///<exception cref="T:System.IndexOutOfRangeException">No column with the specified name was found. </exception><filterpriority>2</filterpriority>
		public virtual object this[string name]
		{
			get
			{
				return reader[name];
			}
		}

		#endregion
	}
}
